﻿//Copyright (c) 2010, Andreas Grünwald
//All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Threading;

namespace yaTDL.Core.MVVM
{
    public class ProjectTaskListViewModel : TaskListViewModelBase
    {
        #region Fields

        string _projectId;

        #endregion

        #region Properties

        public string ProjectId
        {
            get { return _projectId; }
            set
            {
                if (value != _projectId)
                {
                    if (!string.IsNullOrEmpty(_projectId) && _projectId != "0") TaskStore.GetProject(_projectId).PropertyChanged -= Project_PropertyChanged;
                    _projectId = value;
                    RaisePropertyChanged("ProjectId");
                    if (!string.IsNullOrEmpty(_projectId) && _projectId != "0" && TaskStore.ProjectExists(_projectId)) TaskStore.GetProject(_projectId).PropertyChanged += Project_PropertyChanged;
                    projectIdChanged();
                }
            }
        }

        #endregion


        #region Constructor and private methods

        public ProjectTaskListViewModel(string projectId) : base()
        {
            ProjectId = projectId;

            if (!string.IsNullOrEmpty(_projectId) && _projectId != "0") 
            {
                TaskStore.GetProject(projectId).PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(Project_PropertyChanged);            
            }                                
            
        }
       
              

        private void Project_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (!Application.Current.Dispatcher.CheckAccess())
            {
                Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() { Project_PropertyChanged(sender, e); }));
                return;
            }
            

            if (e.PropertyName == "Id")
            {
                ProjectId = (sender as Project).Id;
            }
            if (e.PropertyName == "Name")
            {
                if ((sender as Project).Id == ProjectId)
                {
                    ListHeader = String.Format("Project: {0}", (sender as Project).Name);
                }
            }

        }


        protected override void TaskStore_TaskAdded(object sender, TaskEventArgs e)
        {
            if (e.Task.ProjectId == this._projectId || String.IsNullOrEmpty(_projectId))
            {
                ObservableCollection<Task> tasks = e.Task.Completed ? CompletedItems : PendingItems;

                tasks.Add(e.Task);
            }
        }
        

        protected override void TaskStore_TaskPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                //if the Task's InHistory Property has changed and it is currectly displayed it has to be moved from Completed- to PendingItems or vice versa.
                case "InHistory":
                    //determine whether Task is currently displayed and remove/move it when necessary
                    if (!(sender as Task).Completed)
                    {
                        //if the old value was true, it is now false and thus could be a element of CompletedItems
                        if (CompletedItems.Contains(sender as Task))
                        {
                            CompletedItems.Remove(sender as Task);
                            PendingItems.Add(sender as Task);
                        }
                    }
                    else
                    {
                        if (PendingItems.Contains(sender as Task))
                        {
                            PendingItems.Remove(sender as Task);
                            CompletedItems.Add(sender as Task);
                        }
                    }
                    break;

                //if a Tasks's ProjectId has changed, it will have to be removed if it curently is displayed or it has to be added if it is now part of the displayed Project
                case "ProjectId":                   
                        switch ((sender as Task).Completed)
                        {
                            case true:
                                if (CompletedItems.Contains(sender as Task))
                                {
                                    CompletedItems.Remove(sender as Task);
                                }
                                break;
                            case false:
                                if (PendingItems.Contains(sender as Task))
                                {
                                    PendingItems.Remove(sender as Task);
                                }
                                break;
                        }
                    

                    if ((sender as Task).ProjectId == this._projectId)
                    {
                        switch ((sender as Task).Completed)
                        {
                            case true:
                                if (!CompletedItems.Contains(sender as Task))
                                {
                                    CompletedItems.Add(sender as Task);
                                }
                                break;
                            case false:
                                if (!PendingItems.Contains(sender as Task))
                                {
                                    PendingItems.Add(sender as Task);
                                }
                                break;
                        }
                    }

                    break;

                //if any other Task Property has changed, the collection will need to be resorted.
                default:
                    if (DetailsPaneVisibility != Visibility.Visible)        //sorting is very slow. If the Detail-Pane is visible, a Task's data can change very fast, so it is not wise to sort the task-list during that time;
                    {
                        if (AllItems.Contains(sender as Task))
                        {
                            sortAllTaskCollections();
                        }
                    }
                    break;

            }
        }
        
        
        private void projectIdChanged()
        {

            PendingItems.Clear();
            CompletedItems.Clear();
			AllItems.Clear();


            //set the task-list's header
            switch (ProjectId)
            {
                case null:
                case "":
                    ListHeader = "All Tasks";
                    break;
                case "0":
                    ListHeader = "No Project";
                    break;
                default:
                    if (TaskStore.ProjectExists(ProjectId))
                    {
                        ListHeader = String.Format("Project: {0}", TaskStore.GetProject(ProjectId).Name);
                    }
                    else
                    {
                        ListHeader = "";
                    }
                    break;
            }

            
            //get all tasks for the task-list
            Collection<Task> tasks = String.IsNullOrEmpty(ProjectId) ? TaskStore.GetTasks() : TaskStore.GetTasks(ProjectId);

            CompletedItems = new SortableObservableCollection<Task>(tasks.Where(t => t.Completed));
            PendingItems  = new SortableObservableCollection<Task>(tasks.Where(t => !t.Completed));
           
            sortAllTaskCollections();
        }

        

        #endregion


        #region Command Methods

        protected override bool addTaskCommandCanExecute(object parameter)
        {
            return !String.IsNullOrEmpty(this._projectId) ? true : false;
        }

        protected override void addTaskCommandExecute(object parameter)
        {
            Task t = new Task() { Content = "New Task", ProjectId = this._projectId };
            TaskStore.AddTask(t);
            SelectedTask = t;
        }

        protected override bool deleteHistoryCommandCanExecute(object parameter)
        {
            return (!String.IsNullOrEmpty(_projectId) && _projectId != "0") ? true : false;
        }

        protected override void deleteHistoryCommandExecute(object parameter)
        {
            //TODO: request confirmation
            TaskStore.DeleteHistory(_projectId);
        }

        #endregion


    }   


    
}
